﻿using System.Drawing.Imaging;
using System.Drawing;
using System;
using System.Runtime.InteropServices;
using System.IO;

namespace FinalTest_Algonrithm.Clibra
{
    public class HuayaLibCalib
    {

        

        public static string ConfigPath(string recipeName)
        {
            return $"D:\\HY System\\_产品参数\\{recipeName}\\ClibraConfig\\CalibConfigs.ini";
        }

        /* @hy_load_configs: 加载配置文件, 初始化或修改配置文件后调用
            @ConfigPath: para, 配置文件路径
            @nStations: para, 总站位数
            @返回值: TRUE(1), ELSE 查看详细代码
            */
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_load_configs(string ConfigPath, int nStations = 1);

        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_complete_configs(string ConfigPath);

        /* ******* ******* ******** ******* *******   Calib   ******** ******* ******* ******* ******* */

        /* @hy_get_corners: 每次采集图像后传输图像数据，提取角点
            @iStation: para, 工位编号
            @iChartView: para, 拍摄图片序号，图卡不同时需提前定好序号
            @BmpData[H*W*3]: para, 图像数据缓存
            @NewTest: para, 是否为新的测试, dll 会清空历史角点数据记录
            @BmpDest[H*W*3]: ret, 返回处理后的图像
            @返回值: TRUE(1), ELSE 查看详细代码
            */
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_corners(int iStation, int iChartView, byte* BmpData, bool NewTest = false, byte* BmpDest = null);


        
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_folder_image_corners(int iStation, string SourceFigPath);



        /// <summary>
        /// calibModel = 0, 小孔 3K 模型
        /// </summary>
        /// <param name="iStation"></param>
        /// <param name="ReproErr"></param>
        /// <param name="Cx"></param>
        /// <param name="Cy"></param>
        /// <param name="Fx"></param>
        /// <param name="Fy"></param>
        /// <param name="K">K[3]</param>
        /// <param name="P">P[2]</param>
        /// <param name="SourceFigPath">上位机设为 null</param>
        /// <returns></returns>
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_start_calib_cv_pinhole_3k(int iStation, ref double ReproErr, ref double Cx, ref double Cy, ref double Fx, ref double Fy, double[] K, double []P, string SourceFigPath = null);

        /// <summary>
        /// calibModel = 1, 小孔 6K 模型
        /// </summary>
        /// <param name="iStation"></param>
        /// <param name="ReproErr"></param>
        /// <param name="Cx"></param>
        /// <param name="Cy"></param>
        /// <param name="Fx"></param>
        /// <param name="Fy"></param>
        /// <param name="K"></param>
        /// <param name="P"></param>
        /// <param name="SourceFigPath">上位机设为 null</param>
        /// <returns></returns>
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_start_calib_cv_pinhole_6k(int iStation, ref double ReproErr, ref double Cx, ref double Cy, ref double Fx, ref double Fy, double[] K, double []P, string SourceFigPath = null);

        /// <summary>
        /// calibModel = 2, 鱼眼模型
        /// </summary>
        /// <param name="iStation"></param>
        /// <param name="ReproErr"></param>
        /// <param name="Cx"></param>
        /// <param name="Cy"></param>
        /// <param name="Fx"></param>
        /// <param name="Fy"></param>
        /// <param name="K"></param>
        /// <param name="SourceFigPath">上位机设为 null</param>
        /// <returns></returns>
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_start_calib_cv_fisheye(int iStation, ref double ReproErr, ref double Cx, ref double Cy, ref double Fx, ref double Fy, double[] K, string SourceFigPath = null);



        /// <summary>
        /// calibModel = 3, 环视 MEI 模型
        /// </summary>
        /// <param name="iStation"></param>
        /// <param name="ReproErr"></param>
        /// <param name="Cx"></param>
        /// <param name="Cy"></param>
        /// <param name="Fx"></param>
        /// <param name="Fy"></param>
        /// <param name="MeiXi"></param>
        /// <param name="K">K[2]</param>
        /// <param name="P">P[2]</param>
        /// <param name="SourceFigPath">上位机设为 null</param>
        /// <returns></returns>
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_start_calib_cv_omnidir(int iStation, ref double ReproErr, ref double Cx, ref double Cy, ref double Fx, ref double Fy, ref double MeiXi, double[] K, double[] P, string SourceFigPath = null);

        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_start_calib_division(int iStation, ref double ReproErr, ref double Cx, ref double Cy, ref double Fx, ref double Fy, double[] K, string SourceFigPath = null);


        /// <summary>
        /// calibModel = 5, OCAM 模型
        /// </summary>
        /// <param name="iStation"></param>
        /// <param name="ReproErr"></param>
        /// <param name="Cx"></param>
        /// <param name="Cy"></param>
        /// <param name="PolyCoeffs">PolyCoeffs[5]</param>
        /// <param name="InvPoly">InvPoly[20]</param>
        /// <param name="AffineParas">AffineParas[5]</param>
        /// <param name="SourceFigPath">上位机设为 null</param>
        /// <returns></returns>
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_start_calib_ocam(int iStation, ref double ReproErr, ref double Cx, ref double Cy, double[] PolyCoeffs, double[] InvPoly, double[] AffineParas, string SourceFigPath = null);



        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_get_repro_err(int iStation, ref double RmsFigMax, ref double RmsFigMean, ref double Rms95P, ref double Rms90P, ref double Rms85P, ref double Rms80P, ref int nFigs, double[] reproErrFigs);

        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_get_repro_err_ex(int iStation, ref double RmsPtsMean, ref double RmsPtsMax);

        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_coverage(int iStation, ref double Coverage, byte* BmpCov);
        
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_pts_removed_rate(int iStation, ref double PtsRemovedRate);

         [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_undistort_image(int iStation, int iChartView, byte* BmpCov);




        /* @hy_start_calib: 图像传输完成时调用,开始标定
            @iStation: para, 工位编号
            @nEffctChartViews: ret, 有效图片张数
            @CalibResult: 测试结果数组, 根据标定模型不同含义不同, 具体见 #region CalibResult 详细说明
            @返回值: TRUE(1), ELSE 查看详细代码
            */
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_start_calib(int iStation);

        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_start_batch_calib(int iStation, string SourceFigPath);


        #region CalibResult 详细说明
        /* 返回测试结果均为 double 数据类型
         * reproErr: 重投影误差, 反应模型匹配程度, 数值越低匹配度越高
         * Cx, Cy: 畸变中心
         * fx, fy: 焦距
         * k: 径向畸变系数
         * p: 切向畸变系数
         * meiXi: 环视模型参数, 表示光学中心的纵向偏移
         * ...
         * 按如下方式排列
         * calibModel = 0: 一般小孔模型 
            * reproErr, Cx, Cy, fx, fy, k[3], p[2]
         * calibModel = 1: Rational 小孔模型 
            * reproErr, Cx, Cy, fx, fy, k[6], p[2]
         * calibModel = 2: 鱼眼模型 
            * reproErr, Cx, Cy, fx, fy, k[4]
         * calibModel = 3: MEI 模型
            * reproErr, Cx, Cy, fx, fy, k[2], p[2], meiXi
         * calibModel = 4: DIVISION 除法模型
            * reproErr, Cx, Cy, fx, fy, k[4]
         */


        #endregion


        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_start_triangle_test(int iStation, byte* BmpData, int iView, double[] IntrinParas, ref double Err, byte* BmpDest);

        
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_start_auto_triangle_test(int iStation, string SourceFigPath);

        
        // calibModel = 0
        public struct cv_pinhole_3k_intrin
        {
            public double cx;
            public double cy;
            public double fx;
            public double fy;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
            public double[] k;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
            public double[] p;
        }
        public unsafe static int start_triangle_test_cv_pinhole_3k(int iStation, byte* BmpData, int iView, cv_pinhole_3k_intrin IntrinParas, ref double Err, byte* BmpDest)
        {
            double[] Paras = new double[9];
            int index = 0;
            Paras[index++] = IntrinParas.cx;
            Paras[index++] = IntrinParas.cy;
            Paras[index++] = IntrinParas.fx;
            Paras[index++] = IntrinParas.fy;
            for (int i = 0; i < 3; i++)
            {
                Paras[index++] = IntrinParas.k[i];
            }
            for (int i = 0; i < 2; i++)
            {
                Paras[index++] = IntrinParas.p[i];
            }
            return hy_start_triangle_test(iStation, BmpData, iView, Paras, ref Err, BmpDest);
        }

        // calibModel = 1
        public struct cv_pinhole_6k_intrin
        {
            public double cx;
            public double cy;
            public double fx;
            public double fy;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            public double[] k;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
            public double[] p;
        }
        public unsafe static int start_triangle_test_cv_pinhole_6k(int iStation, byte* BmpData, int iView, cv_pinhole_6k_intrin IntrinParas, ref double Err, byte* BmpDest)
        {
            double[] Paras = new double[12];
            int index = 0;
            Paras[index++] = IntrinParas.cx;
            Paras[index++] = IntrinParas.cy;
            Paras[index++] = IntrinParas.fx;
            Paras[index++] = IntrinParas.fy;
            for (int i = 0; i < 6; i++)
            {
                Paras[index++] = IntrinParas.k[i];
            }
            for (int i = 0; i < 2; i++)
            {
                Paras[index++] = IntrinParas.p[i];
            }
            return hy_start_triangle_test(iStation, BmpData, iView, Paras, ref Err, BmpDest);
        }


        // calibModel = 2
        public struct cv_fisheye_intrin
        {
            public double cx;
            public double cy;
            public double fx;
            public double fy;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public double[] k;
        }
        public unsafe static int start_triangle_test_cv_fisheye(int iStation, byte* BmpData, int iView, cv_fisheye_intrin IntrinParas, ref double Err, byte* BmpDest)
        {
            double[] Paras = new double[8];
            int index = 0;
            Paras[index++] = IntrinParas.cx;
            Paras[index++] = IntrinParas.cy;
            Paras[index++] = IntrinParas.fx;
            Paras[index++] = IntrinParas.fy;
            for (int i = 0; i < 4; i++)
            {
                Paras[index++] = IntrinParas.k[i];
            }
            return hy_start_triangle_test(iStation, BmpData, iView, Paras, ref Err, BmpDest);
        }

        // calibModel = 3
        public struct cv_mei_intrin
        {
            public double cx;
            public double cy;
            public double fx;
            public double fy;
            public double meiXi;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
            public double[] k;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
            public double[] p;
        }
        public unsafe static int start_triangle_test_cv_mei(int iStation, byte* BmpData, int iView, cv_mei_intrin IntrinParas, ref double Err, byte* BmpDest)
        {
            double[] Paras = new double[9];
            int index = 0;
            Paras[index++] = IntrinParas.cx;
            Paras[index++] = IntrinParas.cy;
            Paras[index++] = IntrinParas.fx;
            Paras[index++] = IntrinParas.fy;
            Paras[index++] = IntrinParas.meiXi;
            for (int i = 0; i < 2; i++)
            {
                Paras[index++] = IntrinParas.k[i];
            }
            for (int i = 0; i < 2; i++)
            {
                Paras[index++] = IntrinParas.p[i];
            }
            return hy_start_triangle_test(iStation, BmpData, iView, Paras, ref Err, BmpDest);
        }


        // calibModel = 4
        public struct division_intrin
        {
            public double cx;
            public double cy;
            public double fx;
            public double fy;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
            public double[] k;
        }
        public unsafe static int start_triangle_test_division(int iStation, byte* BmpData, int iView, division_intrin IntrinParas, ref double Err, byte* BmpDest)
        {
            double[] Paras = new double[9];
            int index = 0;
            Paras[index++] = IntrinParas.cx;
            Paras[index++] = IntrinParas.cy;
            Paras[index++] = IntrinParas.fx;
            Paras[index++] = IntrinParas.fy;
            for (int i = 0; i < 6; i++)
            {
                Paras[index++] = IntrinParas.k[i];
            }
            return hy_start_triangle_test(iStation, BmpData, iView, Paras, ref Err, BmpDest);
        }


        // calibModel = 5
        public struct ocam_intrin
        {
            public double cx;
            public double cy;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
            public double[] affineParas;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 5)]
            public double[] polyCoeffs;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
            public double[] invPoly;
        }
        public unsafe static int start_triangle_test_ocam(int iStation, byte* BmpData, int iView, ocam_intrin IntrinParas, ref double Err, byte* BmpDest)
        {
            double[] Paras = new double[32];
            int index = 0;
            Paras[index++] = IntrinParas.cx;
            Paras[index++] = IntrinParas.cy;
            for (int i = 0; i < 5; i++)
            {
                Paras[index++] = IntrinParas.affineParas[i];
            }
            for (int i = 0; i < 5; i++)
            {
                Paras[index++] = IntrinParas.polyCoeffs[i];
            }
            for (int i = 0; i < 20; i++)
            {
                Paras[index++] = IntrinParas.invPoly[i];
            }
            return hy_start_triangle_test(iStation, BmpData, iView, Paras, ref Err, BmpDest);
        }






        /* ******* ******* ******** ******* *******   BINARY   ******** ******* ******* ******* ******* */
        /* @hy_get_awb: 二值化
          @iStation: para, 工位编号
          @BmpDest: ret, 返回处理后的图像
          @返回值: TRUE(1), ELSE 查看详细代码
        */
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_binary(int iStation, byte* BmpData, byte* BmpDest = null);


        /* ******* ******* ******** ******* *******   REF MARK   ******** ******* ******* ******* ******* */
        /* @hy_get_ref_mark: 绘制参考线, 十字线、对角线、视场角
          @iStation: para, 工位编号
          @BmpDest: ret, 返回处理后的图像
          @返回值: TRUE(1), ELSE 查看详细代码
        */
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_ref_mark(int iStation, byte* BmpData, byte* BmpDest = null);



        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_get_byd_fisheye_calib(string SourceFolderPath, double[] Results, string iniPath);

        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public static extern int hy_get_byd_extrinsics(string SourceFolderPath, string iniPath);


        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_start_auto_corners(int iStation, byte* BmpData, byte* BmpDest);

        
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_chart_center(int iStation, byte* BmpData, ref double CentX, ref double CentY, byte* BmpDest, int nRows, int nCols);


        
        
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_focal_optimize_load_gold_sample(int iStation, byte* BmpData, ref double HeightVsFx, ref double HeightVsFy);

        
        
        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_corner_steady_state(int iStation, byte* BmpData, bool NewTest,
            ref int nCornerNum, double[] CornerX, double[] CornerY,
            double[] iMaxErrX, double[] iMaxErrY,
            byte* BmpCorners = null, byte* BmpMaxErrs = null);


        [DllImport(@"HuayaLib\HuayaLibCalib.dll", CallingConvention = CallingConvention.Cdecl)]
        public unsafe static extern int hy_get_straightness_err(int iStation, double[] MaxErr, double[] AvgErr);
    }
}